package nl.hro.mgdd.team4.raidersofhexagoniland.Scenes;

import java.io.IOException;
import java.io.InputStream;

import nl.hro.mgdd.team4.raidersofhexagoniland.GameActivity;

import org.andengine.engine.Engine.EngineLock;
import org.andengine.entity.scene.menu.MenuScene;
import org.andengine.entity.sprite.ButtonSprite;
import org.andengine.entity.sprite.ButtonSprite.OnClickListener;
import org.andengine.entity.sprite.Sprite;
import org.andengine.entity.text.Text;
import org.andengine.opengl.font.Font;
import org.andengine.opengl.texture.ITexture;
import org.andengine.opengl.texture.bitmap.BitmapTexture;
import org.andengine.opengl.texture.region.ITextureRegion;
import org.andengine.opengl.texture.region.TextureRegionFactory;
import org.andengine.util.adt.io.in.IInputStreamOpener;
import org.andengine.util.debug.Debug;

import Parts.HexagonTile;
import Parts.HexagonTile.HexagonState;
import Units.*;
import Utils.Array;

public class BattleSetupScene extends MenuScene implements OnClickListener {

	private int _playerBows;
	private int _playerSpears;
	private int _playerSwords;

	private Array<Unit> _playerChosenUnits;
	private Sprite _playerChosenUnit1;
	private Sprite _playerChosenUnit2;
	private Sprite _playerChosenUnit3;
	private Sprite _playerChosenUnit4;
	private Sprite _playerChosenUnit5;

	private ITexture _background;
	private ITextureRegion _backgroundRegion;
	private ITexture _battleButton;
	private ITextureRegion _battleButtonRegion;
	private ITexture _sword;
	private ITexture _spear;
	private ITexture _bow;
	private ITextureRegion _swordRegion;
	private ITextureRegion _spearRegion;
	private ITextureRegion _bowRegion;

	private Sprite _playerBowman;
	private Sprite _playerSpearman;
	private Sprite _playerSwordman;
	private Sprite _bg;
	private Sprite _battleBtn;

	private Text _playerUnitCount;
	private Text _enemyUnitCount;

	private Font _f;

	private HexagonTile _h;

	public BattleSetupScene(HexagonTile attackedTile) {
		_h = attackedTile;
		_playerBows = SceneManager._player.getBowCount();
		_playerSpears = SceneManager._player.getSpearCount();
		_playerSwords = SceneManager._player.getSwordCount();
		_playerChosenUnits = new Array<Unit>();
		this.setCamera(GameActivity.getCamera());
		this.setBackgroundEnabled(false);
		_f = GameActivity.getFont();
		loadTextures();
		placeTextures();
	}

	private void loadTextures() {
		try {
			SceneManager.getManager();
			this._background = new BitmapTexture(
					SceneManager._game.getTextureManager(),
					new IInputStreamOpener() {

						@Override
						public InputStream open() throws IOException {
							SceneManager.getManager();
							return SceneManager._game.getAssets().open(
									"gfx/battleSetupBg.png");
						}
					});
			this._background.load();
			this._backgroundRegion = TextureRegionFactory
					.extractFromTexture(this._background);

			this._bow = new BitmapTexture(
					SceneManager._game.getTextureManager(),
					new IInputStreamOpener() {

						@Override
						public InputStream open() throws IOException {
							SceneManager.getManager();
							return SceneManager._game.getAssets().open(
									"gfx/archer.png");
						}
					});
			this._bow.load();
			this._bowRegion = TextureRegionFactory
					.extractFromTexture(this._bow);

			this._sword = new BitmapTexture(
					SceneManager._game.getTextureManager(),
					new IInputStreamOpener() {

						@Override
						public InputStream open() throws IOException {
							SceneManager.getManager();
							return SceneManager._game.getAssets().open(
									"gfx/swordman.png");
						}
					});
			this._sword.load();
			this._swordRegion = TextureRegionFactory
					.extractFromTexture(this._sword);

			this._spear = new BitmapTexture(
					SceneManager._game.getTextureManager(),
					new IInputStreamOpener() {

						@Override
						public InputStream open() throws IOException {
							SceneManager.getManager();
							return SceneManager._game.getAssets().open(
									"gfx/spearsman.png");
						}
					});
			this._spear.load();
			this._spearRegion = TextureRegionFactory
					.extractFromTexture(this._spear);

			this._battleButton = new BitmapTexture(
					SceneManager._game.getTextureManager(),
					new IInputStreamOpener() {

						@Override
						public InputStream open() throws IOException {
							SceneManager.getManager();
							return SceneManager._game.getAssets().open(
									"gfx/battleBtn.png");
						}
					});
			this._battleButton.load();
			this._battleButtonRegion = TextureRegionFactory
					.extractFromTexture(this._battleButton);
		} catch (IOException e) {
			Debug.e(e);
		}
	}

	private void placeTextures() {
		_bg = new Sprite(this.mCamera.getCenterX()
				- _backgroundRegion.getWidth() / 2f, this.mCamera.getCenterY()
				- _backgroundRegion.getHeight() / 2f, _backgroundRegion,
				SceneManager._game.getVertexBufferObjectManager());
		attachChild(_bg);

		_battleBtn = new ButtonSprite(this.mCamera.getCenterX()
				+ _backgroundRegion.getWidth() / 2f - 3f
				- _battleButtonRegion.getWidth(), this.mCamera.getCenterY()
				+ _backgroundRegion.getHeight() / 2f - 3f
				- _battleButtonRegion.getHeight(), _battleButtonRegion,
				SceneManager._game.getVertexBufferObjectManager(), this);
		_battleBtn.setTag(992);
		registerTouchArea(_battleBtn);
		attachChild(_battleBtn);

		_playerBowman = new ButtonSprite(this.mCamera.getCenterX()
				- _backgroundRegion.getWidth() / 2f + 3f,
				this.mCamera.getCenterY() - _backgroundRegion.getHeight() / 2f
						+ 3f, _bowRegion,
				SceneManager._game.getVertexBufferObjectManager(), this);
		_playerBowman.setSize(72f, 72f);
		_playerBowman.setTag(999);
		registerTouchArea(_playerBowman);
		attachChild(_playerBowman);

		_playerSpearman = new ButtonSprite(this.mCamera.getCenterX()
				- _backgroundRegion.getWidth() / 2f + 3f,
				this.mCamera.getCenterY() - _backgroundRegion.getHeight() / 2f
						+ 5f + _bowRegion.getHeight(), _spearRegion,
				SceneManager._game.getVertexBufferObjectManager(), this);
		_playerSpearman.setSize(72f, 72f);
		_playerSpearman.setTag(998);
		registerTouchArea(_playerSpearman);
		attachChild(_playerSpearman);

		_playerSwordman = new ButtonSprite(this.mCamera.getCenterX()
				- _backgroundRegion.getWidth() / 2f + 3f,
				this.mCamera.getCenterY() - _backgroundRegion.getHeight() / 2f
						+ 7f + _bowRegion.getHeight()
						+ _spearRegion.getHeight(), _swordRegion,
				SceneManager._game.getVertexBufferObjectManager(), this);
		_playerSwordman.setSize(72f, 72f);
		_playerSwordman.setTag(997);
		registerTouchArea(_playerSwordman);
		attachChild(_playerSwordman);

		if(_playerSwords < 0) _playerSwords = 0;
		if(_playerSpears < 0) _playerSpears = 0;
		if(_playerBows < 0) _playerBows = 0;
		_playerUnitCount = new Text(this.mCamera.getCenterX()
				- _backgroundRegion.getWidth() / 2f + 15f
				+ _bowRegion.getWidth(), this.mCamera.getCenterY()
				- _backgroundRegion.getHeight() / 2f + 24f, _f, (_playerBows < 0 ? 0 : _playerBows)
				+ "\n\n" + (_playerSpears < 0 ? 0 : _playerSpears) + "\n\n" + (_playerSwords < 0 ? 0 : _playerSwords),
				SceneManager._game.getVertexBufferObjectManager());
		attachChild(_playerUnitCount);
		_enemyUnitCount = new Text(this.mCamera.getCenterX()
				+ _backgroundRegion.getWidth() / 2f - 35f,
				this.mCamera.getCenterY() - _backgroundRegion.getHeight() / 2f
						+ 24f, _f, "" + SceneManager._enemy.getBowCount()
						+ "\n\n" + SceneManager._enemy.getSpearCount() + "\n\n"
						+ SceneManager._enemy.getSwordCount(),
				SceneManager._game.getVertexBufferObjectManager());
		attachChild(_enemyUnitCount);
	}

	@Override
	public void onClick(ButtonSprite pButtonSprite, float pTouchAreaLocalX,
			float pTouchAreaLocalY) {
		switch (pButtonSprite.getTag()) {
		case 999:
			// Archer
			if (_playerBows != 0 && _playerChosenUnits.size < 5) {
				_playerBows--;
				_playerChosenUnits.add(new Archer());
			}
			break;
		case 998:
			// Spearman
			if (_playerSpears != 0 && _playerChosenUnits.size < 5) {
				_playerSpears--;
				_playerChosenUnits.add(new Spearman());
			}
			break;
		case 997:
			// Swordman
			if (_playerSwords != 0 && _playerChosenUnits.size < 5) {
				_playerSwords--;
				_playerChosenUnits.add(new Swordman());
			}
			break;
		case 992:
			// Start battle button
			if (_playerChosenUnits.size != 0) {
				handleBattle();
				SceneManager.getManager().getCurrentLevel().setBattleResult(_h);
				this.back();
			}
			break;
		case 804:
			removeSelectedUnit(804);
			break;
		case 803:
			removeSelectedUnit(803);
			break;
		case 802:
			removeSelectedUnit(802);
			break;
		case 801:
			removeSelectedUnit(801);
			break;
		case 800:
			removeSelectedUnit(800);
			break;
		}

		for (int i = 0; i < _playerChosenUnits.size; i++) {
			switch (i) {
			case 0:
				if (_playerChosenUnits.get(i).getTag() == 999)
					_playerChosenUnit1 = new ButtonSprite(
							this.mCamera.getCenterX()
									- _backgroundRegion.getWidth() / 2f + 3f
									+ i * (_playerSpearman.getWidth() + 1f),
							this.mCamera.getCenterY()
									+ _backgroundRegion.getHeight() / 2f - 3f
									- _bowRegion.getHeight(), _bowRegion,
							SceneManager._game.getVertexBufferObjectManager(),
							this);
				else if (_playerChosenUnits.get(i).getTag() == 998)
					_playerChosenUnit1 = new ButtonSprite(
							this.mCamera.getCenterX()
									- _backgroundRegion.getWidth() / 2f + 3f
									+ i * (_playerSpearman.getWidth() + 1f),
							this.mCamera.getCenterY()
									+ _backgroundRegion.getHeight() / 2f - 3f
									- _bowRegion.getHeight(), _spearRegion,
							SceneManager._game.getVertexBufferObjectManager(),
							this);
				else if (_playerChosenUnits.get(i).getTag() == 997)
					_playerChosenUnit1 = new ButtonSprite(
							this.mCamera.getCenterX()
									- _backgroundRegion.getWidth() / 2f + 3f
									+ i * (_playerSpearman.getWidth() + 1f),
							this.mCamera.getCenterY()
									+ _backgroundRegion.getHeight() / 2f - 3f
									- _bowRegion.getHeight(), _swordRegion,
							SceneManager._game.getVertexBufferObjectManager(),
							this);
				_playerChosenUnit1.setSize(72f, 72f);
				_playerChosenUnit1.setTag(800);
				registerTouchArea(_playerChosenUnit1);
				attachChild(_playerChosenUnit1);
				break;
			case 1:
				if (_playerChosenUnits.get(i).getTag() == 999)
					_playerChosenUnit2 = new ButtonSprite(
							this.mCamera.getCenterX()
									- _backgroundRegion.getWidth() / 2f + 3f
									+ i * (_playerSpearman.getWidth() + 1f),
							this.mCamera.getCenterY()
									+ _backgroundRegion.getHeight() / 2f - 3f
									- _bowRegion.getHeight(), _bowRegion,
							SceneManager._game.getVertexBufferObjectManager(),
							this);
				else if (_playerChosenUnits.get(i).getTag() == 998)
					_playerChosenUnit2 = new ButtonSprite(
							this.mCamera.getCenterX()
									- _backgroundRegion.getWidth() / 2f + 3f
									+ i * (_playerSpearman.getWidth() + 1f),
							this.mCamera.getCenterY()
									+ _backgroundRegion.getHeight() / 2f - 3f
									- _bowRegion.getHeight(), _spearRegion,
							SceneManager._game.getVertexBufferObjectManager(),
							this);
				else if (_playerChosenUnits.get(i).getTag() == 997)
					_playerChosenUnit2 = new ButtonSprite(
							this.mCamera.getCenterX()
									- _backgroundRegion.getWidth() / 2f + 3f
									+ i * (_playerSpearman.getWidth() + 1f),
							this.mCamera.getCenterY()
									+ _backgroundRegion.getHeight() / 2f - 3f
									- _bowRegion.getHeight(), _swordRegion,
							SceneManager._game.getVertexBufferObjectManager(),
							this);
				_playerChosenUnit2.setSize(72f, 72f);
				_playerChosenUnit2.setTag(801);
				registerTouchArea(_playerChosenUnit2);
				attachChild(_playerChosenUnit2);
				break;
			case 2:
				if (_playerChosenUnits.get(i).getTag() == 999)
					_playerChosenUnit3 = new ButtonSprite(
							this.mCamera.getCenterX()
									- _backgroundRegion.getWidth() / 2f + 3f
									+ i * (_playerSpearman.getWidth() + 1f),
							this.mCamera.getCenterY()
									+ _backgroundRegion.getHeight() / 2f - 3f
									- _bowRegion.getHeight(), _bowRegion,
							SceneManager._game.getVertexBufferObjectManager(),
							this);
				else if (_playerChosenUnits.get(i).getTag() == 998)
					_playerChosenUnit3 = new ButtonSprite(
							this.mCamera.getCenterX()
									- _backgroundRegion.getWidth() / 2f + 3f
									+ i * (_playerSpearman.getWidth() + 1f),
							this.mCamera.getCenterY()
									+ _backgroundRegion.getHeight() / 2f - 3f
									- _bowRegion.getHeight(), _spearRegion,
							SceneManager._game.getVertexBufferObjectManager(),
							this);
				else if (_playerChosenUnits.get(i).getTag() == 997)
					_playerChosenUnit3 = new ButtonSprite(
							this.mCamera.getCenterX()
									- _backgroundRegion.getWidth() / 2f + 3f
									+ i * (_playerSpearman.getWidth() + 1f),
							this.mCamera.getCenterY()
									+ _backgroundRegion.getHeight() / 2f - 3f
									- _bowRegion.getHeight(), _swordRegion,
							SceneManager._game.getVertexBufferObjectManager(),
							this);
				_playerChosenUnit3.setSize(72f, 72f);
				_playerChosenUnit3.setTag(802);
				registerTouchArea(_playerChosenUnit3);
				attachChild(_playerChosenUnit3);
				break;
			case 3:
				if (_playerChosenUnits.get(i).getTag() == 999)
					_playerChosenUnit4 = new ButtonSprite(
							this.mCamera.getCenterX()
									- _backgroundRegion.getWidth() / 2f + 3f
									+ i * (_playerSpearman.getWidth() + 1f),
							this.mCamera.getCenterY()
									+ _backgroundRegion.getHeight() / 2f - 3f
									- _bowRegion.getHeight(), _bowRegion,
							SceneManager._game.getVertexBufferObjectManager(),
							this);
				else if (_playerChosenUnits.get(i).getTag() == 998)
					_playerChosenUnit4 = new ButtonSprite(
							this.mCamera.getCenterX()
									- _backgroundRegion.getWidth() / 2f + 3f
									+ i * (_playerSpearman.getWidth() + 1f),
							this.mCamera.getCenterY()
									+ _backgroundRegion.getHeight() / 2f - 3f
									- _bowRegion.getHeight(), _spearRegion,
							SceneManager._game.getVertexBufferObjectManager(),
							this);
				else if (_playerChosenUnits.get(i).getTag() == 997)
					_playerChosenUnit4 = new ButtonSprite(
							this.mCamera.getCenterX()
									- _backgroundRegion.getWidth() / 2f + 3f
									+ i * (_playerSpearman.getWidth() + 1f),
							this.mCamera.getCenterY()
									+ _backgroundRegion.getHeight() / 2f - 3f
									- _bowRegion.getHeight(), _swordRegion,
							SceneManager._game.getVertexBufferObjectManager(),
							this);
				_playerChosenUnit4.setSize(72f, 72f);
				_playerChosenUnit4.setTag(803);
				registerTouchArea(_playerChosenUnit4);
				attachChild(_playerChosenUnit4);
				break;
			case 4:
				if (_playerChosenUnits.get(i).getTag() == 999)
					_playerChosenUnit5 = new ButtonSprite(
							this.mCamera.getCenterX()
									- _backgroundRegion.getWidth() / 2f + 3f
									+ i * (_playerSpearman.getWidth() + 1f),
							this.mCamera.getCenterY()
									+ _backgroundRegion.getHeight() / 2f - 3f
									- _bowRegion.getHeight(), _bowRegion,
							SceneManager._game.getVertexBufferObjectManager(),
							this);
				else if (_playerChosenUnits.get(i).getTag() == 998)
					_playerChosenUnit5 = new ButtonSprite(
							this.mCamera.getCenterX()
									- _backgroundRegion.getWidth() / 2f + 3f
									+ i * (_playerSpearman.getWidth() + 1f),
							this.mCamera.getCenterY()
									+ _backgroundRegion.getHeight() / 2f - 3f
									- _bowRegion.getHeight(), _spearRegion,
							SceneManager._game.getVertexBufferObjectManager(),
							this);
				else if (_playerChosenUnits.get(i).getTag() == 997)
					_playerChosenUnit5 = new ButtonSprite(
							this.mCamera.getCenterX()
									- _backgroundRegion.getWidth() / 2f + 3f
									+ i * (_playerSpearman.getWidth() + 1f),
							this.mCamera.getCenterY()
									+ _backgroundRegion.getHeight() / 2f - 3f
									- _bowRegion.getHeight(), _swordRegion,
							SceneManager._game.getVertexBufferObjectManager(),
							this);
				_playerChosenUnit5.setSize(72f, 72f);
				_playerChosenUnit5.setTag(804);
				registerTouchArea(_playerChosenUnit5);
				attachChild(_playerChosenUnit5);
				break;
			}
		}
		updatePlayerText();
	}

	private void updatePlayerText() {
		final EngineLock lock = SceneManager._game.getEngine().getEngineLock();
		lock.lock();
		this.detachChild(_playerUnitCount);
		_playerUnitCount.dispose();
		_playerUnitCount = null;
		lock.unlock();
		if(_playerSwords < 0) _playerSwords = 0;
		if(_playerSpears < 0) _playerSpears = 0;
		if(_playerBows < 0) _playerBows = 0;
		_playerUnitCount = new Text(this.mCamera.getCenterX()
				- _backgroundRegion.getWidth() / 2f + 15f
				+ _bowRegion.getWidth(), this.mCamera.getCenterY()
				- _backgroundRegion.getHeight() / 2f + 24f, _f, _playerBows
				+ "\n\n" + _playerSpears + "\n\n" + _playerSwords,
				SceneManager._game.getVertexBufferObjectManager());
		attachChild(_playerUnitCount);
	}

	private void removeSelectedUnit(int tag) {
		if (_playerChosenUnits.get(tag - 800).getTag() == 999)
			_playerBows++;
		else if (_playerChosenUnits.get(tag - 800).getTag() == 998)
			_playerSpears++;
		else if (_playerChosenUnits.get(tag - 800).getTag() == 997)
			_playerSwords++;
		_playerChosenUnits.removeIndex(tag - 800);
		final EngineLock lock = SceneManager._game.getEngine().getEngineLock();
		lock.lock();
		if (_playerChosenUnit1 != null) {
			unregisterTouchArea(_playerChosenUnit1);
			detachChild(_playerChosenUnit1);
			_playerChosenUnit1.dispose();
			_playerChosenUnit1 = null;
		}
		if (_playerChosenUnit2 != null) {
			unregisterTouchArea(_playerChosenUnit2);
			detachChild(_playerChosenUnit2);
			_playerChosenUnit2.dispose();
			_playerChosenUnit2 = null;
		}
		if (_playerChosenUnit3 != null) {
			unregisterTouchArea(_playerChosenUnit3);
			detachChild(_playerChosenUnit3);
			_playerChosenUnit3.dispose();
			_playerChosenUnit3 = null;
		}
		if (_playerChosenUnit4 != null) {
			unregisterTouchArea(_playerChosenUnit4);
			detachChild(_playerChosenUnit4);
			_playerChosenUnit4.dispose();
			_playerChosenUnit4 = null;
		}
		if (_playerChosenUnit5 != null) {
			unregisterTouchArea(_playerChosenUnit5);
			detachChild(_playerChosenUnit5);
			_playerChosenUnit5.dispose();
			_playerChosenUnit5 = null;
		}
		lock.unlock();
	}

	private void updateEnemyText() {
		final EngineLock lock = SceneManager._game.getEngine().getEngineLock();
		lock.lock();
		detachChild(_enemyUnitCount);
		_enemyUnitCount.dispose();
		_enemyUnitCount = null;
		lock.unlock();
		_enemyUnitCount = new Text(this.mCamera.getCenterX()
				+ _backgroundRegion.getWidth() / 2f - 35f,
				this.mCamera.getCenterY() - _backgroundRegion.getHeight() / 2f
						+ 24f, _f, "" + SceneManager._enemy.getBowCount()
						+ "\n\n" + SceneManager._enemy.getSpearCount() + "\n\n"
						+ SceneManager._enemy.getSwordCount(),
				SceneManager._game.getVertexBufferObjectManager());
		attachChild(_enemyUnitCount);
	}

	private void handleBattle() {
		Array<Unit> tileUnits = _h.getUnits();
		int e = 0;
		int p = 0;
		int eBow = 0, eSpear = 0, eSword = 0;
		for (; p < _playerChosenUnits.size; p++) {
			if (e == tileUnits.size - 1)
				break;
			while (true) {
				if (tileUnits.get(e).getHealth() <= 0) {
					if (tileUnits.get(e).getTag() == 999)
						eBow++;
					else if (tileUnits.get(e).getTag() == 998)
						eSpear++;
					else
						eSword++;
					e++;
					break;
				} else if (_playerChosenUnits.get(p).getHealth() <= 0) {
					if (_playerChosenUnits.get(p).getTag() == 999)
						_playerBows--;
					else if (_playerChosenUnits.get(p).getTag() == 998)
						_playerSpears--;
					else
						_playerSwords--;
					break;
				} else {
					tileUnits.get(e).recieveDamage(
							_playerChosenUnits.get(p).dealDamage());
					_playerChosenUnits.get(p).recieveDamage(
							tileUnits.get(e).dealDamage());
				}
			}
		}
		SceneManager._player.setPLayerUnits(_playerBows, _playerSwords,
				_playerSpears);
		SceneManager._enemy.setPLayerUnits(SceneManager._enemy.getBowCount()
				- eBow, SceneManager._enemy.getSwordCount() - eSword,
				SceneManager._enemy.getSpearCount() - eSpear);
		updatePlayerText();
		updateEnemyText();
		if (p == _playerChosenUnits.size - 1) {
			// player defeated
			Array<Unit> survivors = new Array<Unit>();
			for (; e < tileUnits.size; e++)
				survivors.add(tileUnits.get(e));
			_h.setUnits(survivors);
		} else {
			// enemy defeated
			_h.setState(HexagonState.Free);
			_h.setUnits(null);
		}
	}
}
